home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Programmer Power Tools
/
Programmer Power Tools.iso
/
progjrn
/
pj_6_1.arc
/
PJ5-2.ASM
< prev
next >
Wrap
Assembly Source File
|
1987-12-28
|
8KB
|
321 lines
; Program to illustrate high-speed text-drawing operation of
; write mode 3 of the VGA.
; Draws a string of 8x14 characters at arbitrary locations
; without disturbing the background, using VGA's 8x14 ROM font.
; Designed for use with modes 0Dh, 0Eh, 0Fh, 10h, and 12h.
; Runs only on VGAs (in Models 50 & up and IBM Display Adapter
; and 100% compatibles).
; Assembled with MASM 4.0, linked with LINK 3.51.
; By Michael Abrash, 9/1/87.
; Page 22, Volume 6.1 Programmer's Journal
;
stack segment para stack 'STACK'
db 512 dup(?)
stack ends
;
VGA_VIDEO_SEGMENT equ 0a000h ;VGA display memory segment
SCREEN_WIDTH_IN_BYTES equ 044ah ;offset of BIOS variable
FONT_CHARACTER_SIZE equ 14 ;# bytes in each font char
;
; VGA register equates.
;
SC_INDEX equ 3c4h ;SC index register
SC_MAP_MASK equ 2 ;SC map mask register index
GC_INDEX equ 3ceh ;GC index register
GC_SET_RESET equ 0 ;GC set/reset register index
GC_ENABLE_SET_RESET equ 1 ;GC enable set/reset register index
GC_ROTATE equ 3 ;GC data rotate/logical function
; register index
GC_MODE equ 5 ;GC Mode register
GC_BIT_MASK equ 8 ;GC bit mask register index
;
dseg segment para common 'DATA'
TEST_TEXT_ROW equ 69 ;row to display test text at
TEST_TEXT_COL equ 17 ;column to display test text at
TEST_TEXT_COLOR equ 0fh ;high intensity white
TestString label byte
db 'Hello, world!',0 ;test string to print.
FontPointer dd ? ;font offset
dseg ends
;
cseg segment para public 'CODE'
assume cs:cseg, ds:dseg
start proc near
mov ax,dseg
mov ds,ax
;
; Select 640x480 graphics mode.
;
mov ax,012h
int 10h
;
; Set the screen to all blue, using the readability of VGA registers
; to preserve reserved bits.
;
mov dx,GC_INDEX
mov al,GC_SET_RESET
out dx,al
inc dx
in al,dx
and al,0f0h
or al,1 ;blue plane only set, others reset
out dx,al
dec dx
mov al,GC_ENABLE_SET_RESET
out dx,al
inc dx
in al,dx
and al,0f0h
or al,0fh ;enable set/reset for all planes
out dx,al
mov dx,VGA_VIDEO_SEGMENT
mov es,dx ;point to display memory
mov di,0
mov cx,8000h ;fill all 32k words
mov ax,0ffffh ;because of set/reset, the value
; written actually doesn't matter
rep stosw ;fill with blue
;
; Set driver to use the 8x14 font.
;
mov ah,11h ;VGA BIOS character generator function,
mov al,30h ; return info subfunction
mov bh,2 ;get 8x14 font pointer
int 10h
call SelectFont
;
; Print the test string.
;
mov si,offset TestString
mov bx,TEST_TEXT_ROW
mov cx,TEST_TEXT_COL
mov ah,TEST_TEXT_COLOR
call DrawString
;
; Wait for a key, then set to text mode & end.
;
mov ah,1
int 21h ;wait for a key
mov ax,3
int 10h ;restore text mode
;
; Exit to DOS.
;
mov ah,4ch
int 21h
Start endp
;
; Subroutine to draw a text string left-to-right in a linear
; graphics mode (0Dh, 0Eh, 0Fh, 010h, 012h) with 8-dot-wide
; characters. Background around the pixels that make up the
; characters is preserved.
; Font used should be pointed to by FontPointer.
;
; Input:
; AH = color to draw string in
; BX = row to draw string on
; CX = column to start string at
; DS:SI = string to draw
;
; Forces ALU function to "move".
; Forces write mode 3.
;
DrawString proc near
push ax
push bx
push cx
push dx
push si
push di
push bp
push ds
;
; Set up set/reset to produce character color, using the readability
; of VGA register to preserve the setting of reserved bits 7-4.
;
mov dx,GC_INDEX
mov al,GC_SET_RESET
out dx,al
inc dx
in al,dx
and al,0f0h
and ah,0fh
or al,ah
out dx,al
;
; Select write mode 3, using the readability of VGA registers
; to leave bits other than the write mode bits unchanged.
;
mov dx,GC_INDEX
mov al,GC_MODE
out dx,al
inc dx
in al,dx
or al,3
out dx,al
mov dx,VGA_VIDEO_SEGMENT
mov es,dx ;point to display memory
;
; Calculate screen address of byte character starts in.
;
push ds ;point to BIOS data segment
sub dx,dx
mov ds,dx
mov di,ds:[SCREEN_WIDTH_IN_BYTES] ;retrieve BIOS
; screen width
pop ds
mov ax,bx ;row
mul di ;calculate offset of start of row
push di ;set aside screen width
mov di,cx ;set aside the column
and cl,0111b ;keep only the column in-byte address
shr di,1
shr di,1
shr di,1 ;divide column by 8 to make a byte address
add di,ax ;and point to byte
;
; Set up the GC rotation. In write mode 3, this is the rotation
; of CPU data before it is ANDed with the Bit Mask register to
; form the bit mask. Force the ALU function to "move". Uses the
; readability of VGA registers to leave reserved bits unchanged.
;
mov dx,GC_INDEX
mov al,GC_ROTATE
out dx,al
inc dx
in al,dx
and al,0e0h
or al,cl
out dx,al
;
; Set up BH as bit mask for left half, BL as rotation for right half.
;
mov bx,0ffffh
shr bh,cl
neg cl
add cl,8
shl bl,cl
;
; Draw all characters, left portion first, then right portion in the
; succeeding byte, using the data rotation to position the character
; across the byte boundary and then using write mode 3 to combine the
; character data with the bit mask to allow the set/reset value (the
; character color) through only for the proper portion (where the
; font bits for the character are 1) of the character for each byte.
; Wherever the font bits for the character are 0, the background
; color is preserved.
; Does not check for case where character is byte-aligned and
; no rotation and only one write is required.
;
; Draw the left portion of each character in the string.
;
pop cx ;get back screen width
push si
push di
push bx
;
; Set the bit mask for the left half of the character.
;
mov dx,GC_INDEX
mov al,GC_BIT_MASK
mov ah,bh
out dx,ax
LeftHalfLoop:
lodsb
and al,al
jz LeftHalfLoopDone
call CharacterUp
inc di ;point to next character location
jmp LeftHalfLoop
LeftHalfLoopDone:
pop bx
pop di
pop si
;
; Draw the right portion of each character in the string.
;
inc di ;right portion of each character is across
; byte boundary
;
; Set the bit mask for the right half of the character.
;
mov dx,GC_INDEX
mov al,GC_BIT_MASK
mov ah,bl
out dx,ax
RightHalfLoop:
lodsb
and al,al
jz RightHalfLoopDone
call CharacterUp
inc di ;point to next character location
jmp RightHalfLoop
RightHalfLoopDone:
;
pop ds
pop bp
pop di
pop si
pop dx
pop cx
pop bx
pop ax
ret
DrawString endp
;
; Draw a character.
;
; Input:
; AL = character
; CX = screen width
; ES:DI = address to draw character at
;
CharacterUp proc near
push cx
push si
push di
push ds
;
; Set DS:SI to point to font and ES to point to display memory.
;
lds si,[FontPointer] ;point to font
;
; Calculate font address of character.
;
mov bl,14 ;14 bytes per character
mul bl
add si,ax ;offset in font segment of character
mov bp,FONT_CHARACTER_SIZE
dec cx ; -1 because one byte per char
CharacterLoop:
lodsb ;get character byte
mov ah,es:[di] ;load latches
stosb ;write character byte
;
; Point to next line of character in display memory.
;
add di,cx
;
dec bp
jnz CharacterLoop
;
pop ds
pop di
pop si
pop cx
ret
CharacterUp endp
;
; Set the pointer to the font to draw from to ES:BP.
;
SelectFont proc near
mov word ptr [FontPointer],bp ;save pointer
mov word ptr [FontPointer+2],es
ret
SelectFont endp
;
cseg ends
end start